/* off_t lseek (int fd, off_t offset, int whence); 
 SEEK_END SEEK_CUR SEEK_SET

 #define _LARGEFILE64_SOURCE
 #include <sys/types.h>
 #include <unistd.h>
 off64_t lseek64(int fd, off64_t offset, int whence);


DISK_PTR 	1T/16K(CHUNK_SIZE) 
off64_t		1T

ssize_t write(int fd, const void *buf, size_t count);
ssize_t read (int fd, void *buf, size_t count);
ssize_t: signed size_t, 2^31,  5M=2^23

*****************************************************************
void sync(void)  commit buffer cache to disk. may return before the actual writing is done.
buffer-dirty-flash daemon (privileged process): int bdflush(int func, long data);
int fsync(int fd); BLOCK, but not ensure the entry of the directory.
int fdatasync(int fd); fsync()-metadata;

*****************************************************************
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
mode: S_IRUSR | S_IWUSR
O_RDWR | O_LARGEFILE | O_NONBLOCK | O_CREAT
*********************************************************************************************************/

#define _LARGEFILE64_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include <stdio.h>
#include <stdlib.h>

#include "defines.h"
#include "sync.h"

static int g_fd=0;
static FILE* log_file=NULL;

STATE sync_write(PTR_DISK _disk, char* _mem, int size)
{
	ssize_t n;
	if (g_fd<=0)
	{
		if (log_file)
		{
			fprintf (log_file,"[WRITE  ]:Invalid file descriptor.\n");
		}
		return IO_WRITE_FAIL;
	}
	lseek64(g_fd, _disk*CHUNK_SIZE, SEEK_SET);
	n=write(g_fd, _mem, size);
	if (log_file)
	{
		fprintf (log_file,"[WRITE  ]:%20d\t\t@%20ld\t%d\n", n, (long int)_disk*CHUNK_SIZE,_disk);
		fflush(log_file);
	}
	return IO_WRITE_SUCCESS;	
}

STATE sync_write_2(PTR_DISK _disk, char** ptr_array, int page_size, int max_table_id)
{
	int i;
	ssize_t n=0;

	if (g_fd<=0)
	{
		if (log_file)
		{
			fprintf (log_file, "[WRITE_2]:Invalid file descriptor.\n");	
		}
		return IO_WRITE_FAIL;
	}
	lseek64(g_fd, _disk*CHUNK_SIZE, SEEK_SET);

	for (i=0; i<=max_table_id; i++)
	{
		n+=write(g_fd, ptr_array[i], page_size);
	}

	if (log_file)
	{
		fprintf(log_file, "[WRITE_2]:%20d byte(s)\n", n);
		fflush(log_file);
	}
	return IO_WRITE_SUCCESS;
}

STATE sync_read_2(PTR_DISK _disk, char** ptr_array, int page_size, int max_table_id)
{
	int i;
	ssize_t n=0;
	if (g_fd<=0)
	{
		if (log_file)
		{
			fprintf (log_file, "[READ_2 ]:Invalid file descriptor.\n");
		}
		return IO_READ_FAIL;
	}
	lseek64(g_fd, _disk*CHUNK_SIZE, SEEK_SET);

	for (i=0; i<=max_table_id; i++)
	{
		n+=read(g_fd, ptr_array[i], page_size);
	}

	if (log_file)
	{
		fprintf (log_file, "READ_2:%20d byte(s)\n", n);
		fflush(log_file);
	}
	return IO_READ_SUCCESS;
}

STATE sync_read(PTR_DISK _disk, char* _mem, int size)
{
	ssize_t n;
	if (g_fd<=0)
	{	
		if (log_file)
		{
			fprintf (log_file, "[READ   ]:Invalid file descriptor.\n");
		}
		return IO_READ_FAIL;
	}

	lseek64(g_fd, _disk*CHUNK_SIZE, SEEK_SET);
	n=read(g_fd, _mem, size);
	if (log_file)
	{
		fprintf (log_file, "[READ   ]:%20d\t\t@%20ld\n",(int)n, (long int)_disk*CHUNK_SIZE);
		fflush(log_file);
	}
	return IO_READ_SUCCESS;
}

STATE sync_init(char *pathname, char* sync_log)
{
	g_fd=open(pathname, O_RDWR | O_LARGEFILE | O_CREAT | O_NONBLOCK, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 
	if (sync_log!=NULL)
	{
		log_file=fopen(sync_log, "w");
		if (log_file==NULL)
		{
			printf ("Create \"%s\" failed. Try using SUDO .\n", sync_log);
			return SYNC_INIT_FAIL;
		}
	}

	if (g_fd<=1) 
	{
		if (log_file)fprintf (log_file, "sync_init_error.FILE_OPEN_FAILED.(May be open/sync_init() twice, bug)\n");
		return SYNC_INIT_FAIL;
	}

	return SYNC_INIT_SUCCESS;
}

void sync_exit()
{
	if (log_file)
	{
		fprintf (log_file, "EXIT.\n");
		fclose(log_file);
	}
	close(g_fd);
}


/* failed: don't know _mem size */
/*
STATE sync_write_chunk(PTR_DISK _disk, char* _mem, int chunk_size);
STATE sync_read_chunk(PTR_DISK _disk, char* _mem, int chunk_size);
*/


